package com.ruoyi.charge.service.impl;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import com.ruoyi.charge.common.GlobalConstant;
import com.ruoyi.charge.domain.vo.NearByChargingStationVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.*;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.BoundGeoOperations;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import com.ruoyi.charge.mapper.ChargingStationMapper;
import com.ruoyi.charge.domain.ChargingStation;
import com.ruoyi.charge.service.IChargingStationService;
import org.springframework.util.ObjectUtils;

/**
 * 充电站Service业务层处理
 * 
 * @author ruoyi
 * @date 2022-11-10
 */
@Service
@Slf4j
public class ChargingStationServiceImpl implements IChargingStationService 
{
    @Autowired
    private ChargingStationMapper chargingStationMapper;

    @Autowired
    RedisTemplate redisTemplate;

    @Override
    public List<NearByChargingStationVO> selectNearbyStation(double longitude, double latitude, double radius) {
        log.debug("业务层_开始处理【查找附近充电桩业务】，请求参数 经度={} ，纬度={} ，半径={}",longitude,latitude,radius);
        ArrayList<NearByChargingStationVO> voList = new ArrayList();
        //Point(double x, double y)
        Point userPosition = new Point(longitude, latitude);
        //Metrics
        Distance distance = new Distance(radius, Metrics.KILOMETERS);
        //Distance(double value, Metric metric)
        Circle circle = new Circle(userPosition, distance);
        //Circle(Point center, Distance radius)
        //public static GeoRadiusCommandArgs newGeoRadiusArgs()
        RedisGeoCommands.GeoRadiusCommandArgs geoRadiusCommandArgs = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs();
        geoRadiusCommandArgs.includeCoordinates();//设置返回的充电站包括坐标信息
        geoRadiusCommandArgs.includeDistance();//设置返回的充电站包含距离信息
        //GeoResults<GeoLocation<M>> geoRadius(Circle within, GeoRadiusCommandArgs args)
        BoundGeoOperations boundGeoOperations = redisTemplate.boundGeoOps(GlobalConstant.STATION_GEO_ZSET);
        //String是充电站编号的类型
        GeoResults<RedisGeoCommands.GeoLocation<String>> geoResults = boundGeoOperations.radius(circle, geoRadiusCommandArgs);
        System.out.println(geoResults);

        Iterator<GeoResult<RedisGeoCommands.GeoLocation<String>>> iterator = geoResults.iterator();
        BoundHashOperations boundHashOperations = redisTemplate.boundHashOps(GlobalConstant.STATION_DETAIL_HASH);
        while(iterator.hasNext()){
            GeoResult<RedisGeoCommands.GeoLocation<String>> geoResult = iterator.next();
            String stationId = geoResult.getContent().getName().toString();
            double stationDistance = geoResult.getDistance().getValue();
            //去redis中取充电站详情
            ChargingStation chargingStation = (ChargingStation) boundHashOperations.get(stationId);

            NearByChargingStationVO nearByChargingStationVO = new NearByChargingStationVO();

            BeanUtils.copyProperties(chargingStation,nearByChargingStationVO);

            nearByChargingStationVO.setDistance(stationDistance);

            voList.add(nearByChargingStationVO);

        }
        return voList;
    }

    /**
     * 查询充电站
     * 
     * @param id 充电站主键
     * @return 充电站
     */
    @Override
    public ChargingStation selectChargingStationById(Integer id)
    {
        //从数据库查询慢
        // return chargingStationMapper.selectChargingStationById(id);
        BoundHashOperations boundHashOperations = redisTemplate.boundHashOps(GlobalConstant.STATION_DETAIL_HASH);
        //保证所有充电站信息在redis中，往数据库中添加信息后要立刻同步到redis
        ChargingStation chargingStation = (ChargingStation) boundHashOperations.get(id);
        //redis中有可能查不到，redis也有可能宕机了
        if (ObjectUtils.isEmpty(chargingStation)){
            //redis中没有，从数据库中查
            chargingStation=chargingStationMapper.selectChargingStationById(id);
        }
        return chargingStation;
    }

    /**
     * 查询充电站列表
     * 
     * @param chargingStation 充电站
     * @return 充电站
     */
    @Override
    public List<ChargingStation> selectChargingStationList(ChargingStation chargingStation)
    {
        return chargingStationMapper.selectChargingStationList(chargingStation);
    }

    /**
     * 新增充电站
     * 
     * @param chargingStation 充电站
     * @return 结果
     */
    @Override
    public int insertChargingStation(ChargingStation chargingStation)
    {
        return chargingStationMapper.insertChargingStation(chargingStation);
    }

    /**
     * 修改充电站
     * 
     * @param chargingStation 充电站
     * @return 结果
     */
    @Override
    public int updateChargingStation(ChargingStation chargingStation)
    {
        return chargingStationMapper.updateChargingStation(chargingStation);
    }

    /**
     * 批量删除充电站
     * 
     * @param ids 需要删除的充电站主键
     * @return 结果
     */
    @Override
    public int deleteChargingStationByIds(Integer[] ids)
    {
        return chargingStationMapper.deleteChargingStationByIds(ids);
    }

    /**
     * 删除充电站信息
     * 
     * @param id 充电站主键
     * @return 结果
     */
    @Override
    public int deleteChargingStationById(Integer id)
    {
        return chargingStationMapper.deleteChargingStationById(id);
    }
}
